package com.xtaller.lazy.api.system;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xtaller.lazy.base.TApi;
import com.xtaller.lazy.lib.R;
import com.xtaller.lazy.lib.annotation.Permission;
import com.xtaller.lazy.lib.convert.*;
import com.xtaller.lazy.model.base.Department;
import com.xtaller.lazy.model.base.User;
import com.xtaller.lazy.model.system.Dict;
import com.xtaller.lazy.parameter.DocDict;
import com.xtaller.lazy.service.system.DictService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * @version V1.0
 * @author: Taller
 * @date: 2019-04-23
 * @Description: 数据字典api
 */
@Api(tags = "数据字典api")
@RestController
@RequestMapping("/v1/system")
public class DictApi extends TApi {
    @Autowired private DictService dictService;

    private Map<String, String> baseVerify() {
        var verify = M.create("name", "字典名称不能为空")
                        .put("code", "字典编码不能为空")
                        .put("parentId", "所属上级id不能为空");
        return verify;
    }

    @GetMapping("/dictByParent")
    @ApiOperation("读取字典数据")
    @Permission(authorities = "system-dict-by-parent-id")
    public Object getSub(@ApiParam("页码") @RequestParam(value = "page", required = false, defaultValue = "1") int page,
                         @ApiParam("页长") @RequestParam(value = "limit", required = false, defaultValue = "50") int limit,
                         @ApiParam("页长") @RequestParam(value = "parentId", required = false, defaultValue = "-1") Long parentId){
        var p = new Page<Dict>(page, limit);
        var qw = new QueryWrapper<Dict>();
        qw.lambda().eq(Dict::getParentId, parentId)
                .orderByDesc(Dict::getOrderNumber);
        return p2t(dictService.page(p, qw));
    }

    @GetMapping("/dict")
    @ApiOperation("读取字典数据")
    @Permission(authorities = "system-dict-tree")
    public Object tree(){
        var qw = new QueryWrapper<Dict>();
        qw.lambda().orderByDesc(Dict::getOrderNumber);
        var dicts = dictService.list(qw);
        // 创建一个默认顶级数据
        if(dicts.size() == 0){
            var dict = new Dict();
            dict.setName("数据字典");
            dict.setShortName("字典");
            dict.setPy("SJZD");
            dict.setCode("data-dict");
            dict.setParentId(0L);
            dictService.save(dict);
            dicts = dictService.list(qw);
        }
        var list = formatDict(dicts);
        var data = J.create("list", list).put("tree", L.list2Tree(list, 0L));
        return R.ok(data);
    }

    @PostMapping("/dict")
    @ApiOperation("创建")
    @Permission(authorities = "system-dict-create")
    public Object create(@ApiParam("数据对象") @RequestBody DocDict object){
        var check = V.checkEmpty(baseVerify(), object);
        if (check.getBoolean(CHECK)) {
            return R.error(check.getString(MESSAGE));
        }
        // 唯一性判断
        var qw = new QueryWrapper<Dict>();
        qw.lambda().eq(Dict::getCode, object.getCode());
        var dicts = dictService.list(qw);
        if(dicts.size() > 0){
            return R.error("当前字典code已经存在");
        }
        qw.lambda().eq(Dict::getName, object.getName())
                .eq(Dict::getParentId, object.getParentId());
        dicts = dictService.list(qw);
        if(dicts.size() > 0){
            return R.error("同级下已经有相同相同名称的信息");
        }

        var model = J.o2m(object, Dict.class);
        model.setCreateId(userId.get());
        model.setPy(S.getPinYinHeadChar(object.getName()));
        model = dictService.model(model);

        if(model == null) {
            return R.error("数据创建失败");
        }
        return R.ok("数据创建成功", model);
    }

    @PutMapping("/dict/{id}")
    @ApiOperation("修改数据")
    @Permission(authorities = "system-dict-update")
    public Object update(@ApiParam("数据id") @PathVariable Long id,
                         @ApiParam("数据对象") @RequestBody DocDict object){
        var model = dictService.getById(id);
        if(model == null) {
            return R.error("数据id异常");
        }
        var check = V.checkEmpty(baseVerify(), object);
        if (check.getBoolean(CHECK)) {
            return R.error(check.getString(MESSAGE));
        }

        // 唯一性判断
        var qw = new QueryWrapper<Dict>();
        qw.lambda().eq(Dict::getCode, object.getCode()).ne(Dict::getId, id);
        var dicts = dictService.list(qw);
        if(dicts.size() > 0){
            return R.error("当前字典code已经存在");
        }
        qw.lambda().eq(Dict::getName, object.getName())
                .eq(Dict::getParentId, object.getParentId());
        dicts = dictService.list(qw);
        if(dicts.size() > 0){
            return R.error("同级下已经有相同相同名称的信息");
        }

        model = J.o2m(object, Dict.class);
        model.setId(id);
        model.setUpdateId(userId.get());
        model.setPy(S.getPinYinHeadChar(object.getName()));

        model = dictService.model(model);
        if(model == null) {
            return R.error("数据修改失败");
        }else {
            return R.ok("数据修改成功", model);
        }
    }

    @DeleteMapping("/dict/{id}")
    @ApiOperation("删除数据")
    @Permission(authorities = "system-dict-delete")
    public Object delete(@ApiParam("数据id") @PathVariable Long id){
        var model = dictService.getById(id);
        if(model == null){
            return R.error("数据id异常");
        }
        if(model.getParentId().longValue() == 0L){
            return R.error("禁止删除顶层部门数据");
        }

        var dqw = new QueryWrapper<Dict>();
        dqw.lambda().eq(Dict::getParentId, id);
        var dicts = dictService.list(dqw);
        if(dicts.size() > 0){
            return R.error("该字典数据下有子级信息禁止直接删除");
        }

        if(dictService.removeById(id)) {
            return R.ok("数据删除成功", J.create("id", id));
        }
        return R.error("数据删除失败");
    }


}
